{
  "openapi": "3.1.0",
  "info": {
    "title": "Открытый API общих ресурсов",
    "description": "Управляйте общими ресурсами (прокси, группами и тегами) через открытый API MoreLogin.\n\n**Базовый URL**: `https://api.morelogin.com`\n\nАутентификация выполняется с помощью токена OAuth2 Bearer. Подробности см. в разделе [Аутентификация](../Getting%20Started/authentication.md).\n",
    "version": "2026-09-05"
  },
  "tags": [
    {
      "name": "Proxy Management",
      "description": "Создание, обновление, удаление и просмотр настроек прокси"
    },
    {
      "name": "Group Management",
      "description": "Создание, обновление, удаление и просмотр групп окружений"
    },
    {
      "name": "Tag Management",
      "description": "Создание, обновление, удаление и просмотр тегов окружений"
    },
    {
      "name": "Webhook Management",
      "description": "Настройка эндпоинта обратного вызова команды, который принимает события вебхуков"
    }
  ],
  "paths": {
    "/proxyInfo/page": {
      "post": {
        "summary": "Получение списка прокси-серверов",
        "deprecated": false,
        "description": "Постранично выводит конфигурации прокси команды.\n- **Эффект**: отсутствует. Только чтение. Повтор безопасен при ограниченной выдержке.\n- **Примечание**: пароли не возвращаются обычным участникам, а также для облачных и динамических прокси. Динамические прокси отображаются здесь, но управляются в другом месте и не редактируются через эндпоинты прокси.",
        "operationId": "queryProxyInfoPageUsingPOST",
        "tags": [
          "Proxy Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^\\d+$",
                    "description": "Необязательный ID прокси для точного совпадения. Передавайте 64-битный ID десятичной строкой во избежание потери точности. Не указывайте его, чтобы не фильтровать по ID. Остальные фильтры и пагинация продолжают действовать.",
                    "example": "1800000000000101"
                  },
                  "pageNo": {
                    "type": "integer",
                    "description": "Номер текущей страницы (начиная с 1)",
                    "example": 1
                  },
                  "pageSize": {
                    "type": "integer",
                    "description": "Количество элементов на странице",
                    "example": 10
                  },
                  "isCloudPhoneProxy": {
                    "type": "boolean",
                    "description": "Используется ли прокси для облачных телефонов.\n- `true`: Исключить локальные и частные IP (например, 127.0.0.1, 360, pia, частные диапазоны)\n- `false`: Вернуть все прокси\n",
                    "example": false
                  },
                  "proxyCategoryType": {
                    "type": "integer",
                    "description": "Категория прокси:\n- `1` = Облачная платформа\n- `2` = Собственный IP\n",
                    "example": 2
                  },
                  "proxyIp": {
                    "type": "string",
                    "description": "Фильтр по IP-адресу прокси (частичное совпадение)",
                    "example": ""
                  },
                  "proxyName": {
                    "type": "string",
                    "description": "Фильтр по названию прокси (частичное совпадение)",
                    "example": ""
                  },
                  "proxyProviders": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "Список ID сервисов прокси. Допустимые значения:\n- `0` = Нет\n- `4` = Oxylabs\n- `5` = Proxys.io\n- `6` = GeoSurf\n- `7` = Luminati\n- `8` = Lumauto\n- `9` = Oxylabsauto\n- `10` = Trojan\n- `11` = Shadowsocks\n- `12` = vmess\n- `13` = ABCPROXY\n- `14` = LunaProxy\n- `15` = IPHTML\n- `16` = PiaProxy\n- `17` = 922S5\n",
                    "example": []
                  },
                  "proxyStatus": {
                    "type": "integer",
                    "description": "Статус назначения прокси:\n- `0` = Обычный\n- `1` = Не назначен\n- `2` = Обновляется\n- `3` = Истёк\n- `4` = Скоро истечёт  \n> Примечание: собственные прокси всегда имеют статус `1`.\n",
                    "example": 1
                  },
                  "proxyCheckStatus": {
                    "type": "integer",
                    "description": "Статус проверки прокси:\n- `0` = Ожидает\n- `1` = Успешно\n- `2` = Неудачно\n- `3` = Неизвестная ошибка\n",
                    "example": 1
                  },
                  "proxyTypes": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "Типы протоколов прокси:\n- `0` = HTTP\n- `1` = HTTPS\n- `2` = SOCKS5\n- `3` = SSH\n",
                    "example": []
                  }
                },
                "required": []
              },
              "example": {
                "id": "1800000000000101",
                "pageNo": 1,
                "pageSize": 10,
                "isCloudPhoneProxy": false,
                "proxyCategoryType": 2,
                "proxyIp": "",
                "proxyName": "",
                "proxyProviders": [],
                "proxyStatus": 1,
                "proxyCheckStatus": 1,
                "proxyTypes": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data.dataList` содержит записи запрошенной страницы и является пустым массивом при отсутствии совпадений; `data.total`, `data.current` и `data.pages` описывают постраничную разбивку.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "current": {
                          "type": "string"
                        },
                        "dataList": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "expiryTime": {
                                "description": "Время истечения",
                                "type": "string"
                              },
                              "id": {
                                "description": "Первичный ключ",
                                "type": "string"
                              },
                              "proxyCategoryType": {
                                "description": "Тип прокси: 1 — прокси платформы; 2 — собственный прокси",
                                "type": "integer"
                              },
                              "proxyCheckStatus": {
                                "description": "Статус проверки: 0 — ожидает проверки, 1 — проверка успешна, 2 — проверка не удалась, 3 — неизвестная ошибка",
                                "type": "integer"
                              },
                              "state": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "Штат или область прокси. Приоритет у определённого местоположения выходного IP, затем используется настроенное; возможны null или пустая строка.",
                                "example": "California"
                              },
                              "city": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "Город прокси. Приоритет у определённого местоположения выходного IP, затем используется настроенное; возможны null или пустая строка.",
                                "example": "Los Angeles"
                              },
                              "proxyPort": {
                                "type": [
                                  "integer",
                                  "null"
                                ],
                                "format": "int32",
                                "description": "Порт подключения к прокси; не определяется по имени прокси. Может быть null, если недоступен.",
                                "example": 1080
                              },
                              "proxyIp": {
                                "description": "IP прокси",
                                "type": "string"
                              },
                              "exportIp": {
                                "description": "Внешний IP",
                                "type": "string"
                              },
                              "countryCode": {
                                "description": "countryCode",
                                "type": "string"
                              },
                              "proxyName": {
                                "description": "Название прокси",
                                "type": "string"
                              },
                              "proxyProvider": {
                                "description": "Тип прокси: значение по умолчанию 0 - нет 4-Oxylabs 5-Proxys.io 7-Luminati 8-Lumauto 9-Oxylabsauto 10-Trojan，11-Shadowsocks 13-ABCPROXY 14-LunaProxy 15-IPHTML 16-PiaProxy 17-922S5\n",
                                "type": "integer"
                              },
                              "proxyType": {
                                "description": "Тип прокси: 0 - http, 1 - https, 2 - socks5, 3 - ssh",
                                "type": "integer"
                              },
                              "username": {
                                "description": "Имя пользователя прокси",
                                "type": "string"
                              },
                              "password": {
                                "description": "Пароль прокси",
                                "type": "string"
                              },
                              "refreshUrl": {
                                "description": "URL обновления прокси",
                                "type": "string"
                              }
                            }
                          }
                        },
                        "pages": {
                          "type": "string"
                        },
                        "total": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "current",
                        "dataList",
                        "pages",
                        "total"
                      ]
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": null,
                  "data": {
                    "current": "1",
                    "dataList": [
                      {
                        "expiryTime": "2026-09-01 12:00:00",
                        "id": "1673823102599682",
                        "proxyCategoryType": 1,
                        "proxyCheckStatus": 1,
                        "state": "California",
                        "city": "Los Angeles",
                        "proxyPort": 1080,
                        "proxyIp": "string",
                        "exportIp": "9222",
                        "countryCode": "string",
                        "proxyName": "example-name",
                        "proxyProvider": 1,
                        "proxyType": 1,
                        "username": "example-name",
                        "password": "string",
                        "refreshUrl": "https://example.com/resource"
                      }
                    ],
                    "pages": "1",
                    "total": "1"
                  },
                  "requestId": "0d8b6f1c-9f4e-4d02-9d1a-7c3f5a1b2c3d"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/proxyInfo/add": {
      "post": {
        "summary": "Добавление прокси",
        "deprecated": false,
        "description": "Создаёт конфигурацию прокси в команде.\n- **Предварительные условия**: `proxyPort` обязателен и должен быть в диапазоне 1–65535, а `proxyProvider` должен быть распознаваемым Сервисом.\n- **Эффект**: вставляет запись прокси и возвращает её идентификатор, готовый для привязки к профилям. Сохраняется только конфигурация.\n- **Завершение**: синхронное.\n- **Повтор**: **проверки уникальности имени или конфигурации нет.** Отправка одного и того же тела дважды создаст два прокси с двумя идентификаторами. После таймаута сначала поищите запись в `/proxyInfo/page`, а затем решайте, отправлять ли повторно.\n\nЗадокументированные бизнес-ошибки: `14023`. Значения кодов см. в [Error Codes](../Getting%20Started/error-codes.md). Любая операция может дополнительно вернуть общие коды.",
        "operationId": "addUsingPOST",
        "tags": [
          "Proxy Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "city": {
                    "type": "string",
                    "description": "Город",
                    "example": ""
                  },
                  "country": {
                    "type": "string",
                    "description": "Код страны (ISO 3166-1 alpha-2). Обязателен только если proxyProvider=17.\n",
                    "example": "AD"
                  },
                  "encryptionType": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Тип шифрования; допустимые значения — целые числа от 1 до 14.",
                    "example": 14
                  },
                  "ipChangeAction": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Действие при смене IP: 0 = блокировать, 1 = предупредить",
                    "example": 1
                  },
                  "ipMonitor": {
                    "type": "boolean",
                    "description": "Включить отслеживание смены IP",
                    "example": false
                  },
                  "password": {
                    "type": "string",
                    "description": "Пароль для аутентификации прокси",
                    "example": ""
                  },
                  "proxyIp": {
                    "type": "string",
                    "description": "IP-адрес прокси",
                    "example": "8.10.22.46"
                  },
                  "proxyName": {
                    "type": "string",
                    "description": "Название прокси (поддерживает подстановки вида {{random}})",
                    "example": "sock5_{{random}}"
                  },
                  "proxyPort": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Номер порта прокси",
                    "example": 65534
                  },
                  "proxyProvider": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Тип сервиса прокси:\n0=HTTP, 1=HTTPS, 2=SOCKS5, 3=SSH, 4=Oxylabs, 5=Proxys.io, 6=GeoSurf, 7=Luminati, 8=Lumauto, 9=Oxylabsauto, 10=Trojan, 11=Shadowsocks, 12=vmess, 13=ABCPROXY, 14=LunaProxy, 15=IPHTML, 16=PiaProxy, 17=922S5.\nОсобые правила:\n- Если proxyProvider равен 7 или 8, поле proxyType обязательно.\n- Если proxyProvider равен 17, поле country обязательно; state и city необязательны.\n",
                    "example": 2
                  },
                  "proxyType": {
                    "type": "integer",
                    "format": "int32",
                    "description": "Тип протокола прокси: 0=HTTP, 1=HTTPS, 2=SOCKS5, 3=SSH.\nОбязательно только когда proxyProvider равен 7 или 8.\n",
                    "example": 1
                  },
                  "refreshUrl": {
                    "type": "string",
                    "description": "URL для обновления IP динамического прокси (если поддерживается)",
                    "example": ""
                  },
                  "state": {
                    "type": "string",
                    "description": "Штат/область",
                    "example": ""
                  },
                  "username": {
                    "type": "string",
                    "description": "Имя пользователя для аутентификации прокси",
                    "example": ""
                  }
                },
                "required": [
                  "proxyIp",
                  "proxyPort",
                  "proxyProvider"
                ]
              },
              "example": {
                "proxyIp": "8.10.22.46",
                "proxyPort": 65534,
                "proxyProvider": 2,
                "proxyType": 1,
                "country": "AD",
                "state": "",
                "city": "",
                "encryptionType": 14,
                "ipChangeAction": 1,
                "ipMonitor": false,
                "proxyName": "sock5_{{random}}",
                "refreshUrl": "",
                "username": "",
                "password": ""
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data` — одно значение типа integer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "description": "Идентификатор прокси",
                      "type": "integer"
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": 0,
                  "requestId": "abcd1234"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/proxyInfo/update": {
      "post": {
        "summary": "Изменение информации о прокси-сервере",
        "deprecated": false,
        "description": "Обновляет конфигурацию прокси.\n- **Предварительные условия**: прокси должен существовать в команде. **Динамические прокси через этот эндпоинт обновить нельзя.** Сервис должен быть распознаваемым значением.\n- **Эффект**: это полная перезапись, а не частичное обновление: опущенные вами поля возвращаются к значениям по умолчанию, а не сохраняют текущие. Сначала прочитайте прокси и отправьте его обратно целиком.\n- **Область действия**: привязки профилей сохраняются, потому что меняется только сама запись прокси, но уже запущенные браузер или облачный телефон продолжают использовать данные подключения, с которыми они были запущены. Перезапустите их, чтобы применить новые.\n- **Завершение**: синхронное. Оптимистичной блокировки нет, поэтому при одновременных обновлениях побеждает последняя запись.\n\nЗадокументированные бизнес-ошибки: `14003`, `14023`. Значения кодов см. в [Error Codes](../Getting%20Started/error-codes.md). Любая операция может дополнительно вернуть общие коды.",
        "operationId": "updateProxyUsingPOST",
        "tags": [
          "Proxy Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "proxyIp",
                  "proxyPort",
                  "proxyProvider"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Уникальный ID прокси"
                  },
                  "proxyIp": {
                    "type": "string",
                    "description": "IP-адрес прокси-сервера"
                  },
                  "proxyPort": {
                    "type": "integer",
                    "description": "Порт прокси-сервера"
                  },
                  "proxyName": {
                    "type": "string",
                    "description": "Пользовательское название прокси"
                  },
                  "country": {
                    "type": "string",
                    "description": "Страна (например, \"US\", \"CN\")"
                  },
                  "city": {
                    "type": "string",
                    "description": "Название города"
                  },
                  "username": {
                    "type": "string",
                    "description": "Имя пользователя аутентификации (если требуется)"
                  },
                  "password": {
                    "type": "string",
                    "description": "Пароль аутентификации (если требуется)"
                  },
                  "proxyType": {
                    "type": "integer",
                    "description": "Тип протокола прокси:\n- `0` = HTTP\n- `1` = HTTPS\n- `2` = SOCKS5\n- `3` = SSH\n"
                  },
                  "proxyProvider": {
                    "type": "integer",
                    "description": "ID сервиса прокси:\n- `0` = HTTP\n- `1` = HTTPS\n- `2` = SOCKS5\n- `3` = SSH\n- `4` = Oxylabs\n- `5` = Proxys.io\n- `6` = GeoSurf\n- `7` = Luminati\n- `8` = Lumauto\n- `9` = Oxylabsauto\n- `10` = Trojan\n- `11` = Shadowsocks\n- `12` = vmess\n- `13` = ABCPROXY\n- `14` = LunaProxy\n- `15` = IPHTML\n- `16` = PiaProxy\n- `17` = 922S5\n"
                  },
                  "encryptionType": {
                    "type": "integer",
                    "description": "Тип шифрования (зависит от Сервиса, обычно 0 — без шифрования)"
                  },
                  "ipMonitor": {
                    "type": "boolean",
                    "description": "Включить отслеживание смены IP"
                  },
                  "ipChangeAction": {
                    "type": "integer",
                    "description": "Действие при смене IP:\n- `1` = Уведомить / Обновить (обычное значение)\n> Полный список вариантов см. в документации системы.\n"
                  },
                  "refreshUrl": {
                    "type": "string",
                    "description": "URL для запуска смены IP (если поддерживается Сервисом)"
                  },
                  "state": {
                    "type": "string",
                    "description": "Резервное поле или пользовательское состояние (необязательно)"
                  }
                }
              },
              "example": {
                "id": "1566403036579198",
                "proxyIp": "108.11.23.85",
                "proxyPort": 4096,
                "proxyName": "MyProxy",
                "country": "US",
                "city": "New York",
                "username": "",
                "password": "",
                "proxyType": 0,
                "proxyProvider": 0,
                "encryptionType": 0,
                "ipMonitor": true,
                "ipChangeAction": 1,
                "refreshUrl": "",
                "state": ""
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. Операция не возвращает полезную нагрузку; результат передаётся через `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "requestId": "efgh5678"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/proxyInfo/delete": {
      "post": {
        "summary": "Удалить прокси",
        "deprecated": false,
        "description": "Удаляет одну или несколько конфигураций прокси.\n- **Предварительные условия**: хотя бы один идентификатор должен разрешаться внутри команды; неразрешённые молча игнорируются. **Неистёкший прокси облачной платформы удалить нельзя** — об этом сообщается отдельным кодом ошибки.\n- **Эффект**: собственные прокси удаляются и отвязываются от любого промежуточного сервера. Истёкший прокси облачной платформы вместо этого помечается к освобождению, его подписка отменяется, а IP освобождается **асинхронно**: к моменту возврата ответа освобождение может ещё продолжаться.\n- **Каскадные последствия**: профили и облачные телефоны, привязанные к прокси, **не блокируют удаление и не отвязываются**. Они продолжают ссылаться на удалённый прокси, а запущенные сессии не прерываются. Перед удалением перепривяжите их через `/env/setProxy/batch`.\n- **Повтор**: идентификаторы обрабатываются по одному, и вызов прерывается на первом отказе, поэтому пакет может примениться частично. Перед повтором перечитайте `/proxyInfo/page`.\n\nЗадокументированные бизнес-ошибки: `14017`, `14024`. Значения кодов см. в [Error Codes](../Getting%20Started/error-codes.md). Любая операция может дополнительно вернуть общие коды.",
        "operationId": "deleteProxyUsingPOST",
        "tags": [
          "Proxy Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "integer",
                  "format": "int64"
                }
              },
              "example": [
                1054661322597744600,
                1054661322597744600
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. Операция не возвращает полезную нагрузку; результат передаётся через `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "requestId": "ijkl9012"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envgroup/page": {
      "post": {
        "operationId": "envgroupPagePost",
        "summary": "Получить список групп",
        "deprecated": false,
        "description": "Постранично выводит группы профилей.\n- **Эффект**: отсутствует. Только чтение. Повтор безопасен при ограниченной выдержке.\n- **Примечание**: если команда выдаёт доступ по группам, участник, которому не выдана ни одна группа, получит пустую страницу, а не ошибку.",
        "tags": [
          "Group Management"
        ],
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "groupName": {
                    "type": "string",
                    "title": "Название группы (частичное совпадение)"
                  },
                  "pageNo": {
                    "type": "integer",
                    "title": "Текущая страница"
                  },
                  "pageSize": {
                    "type": "integer",
                    "title": "Элементов на странице"
                  }
                },
                "required": [
                  "groupName",
                  "pageNo",
                  "pageSize"
                ]
              },
              "example": {
                "groupName": "132-kernel",
                "pageNo": 1,
                "pageSize": 10
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data.dataList` содержит записи запрошенной страницы и является пустым массивом при отсутствии совпадений; `data.total`, `data.current` и `data.pages` описывают постраничную разбивку.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "current": {
                          "type": "string"
                        },
                        "dataList": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "description": "Идентификатор группы",
                                "type": "string"
                              },
                              "groupName": {
                                "description": "Название группы",
                                "type": "string"
                              }
                            }
                          }
                        },
                        "pages": {
                          "type": "string"
                        },
                        "total": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "current",
                        "dataList",
                        "pages",
                        "total"
                      ]
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": {
                    "current": "0",
                    "dataList": [
                      {
                        "id": "0",
                        "groupName": ""
                      }
                    ],
                    "pages": "0",
                    "total": "0"
                  },
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envgroup/edit": {
      "post": {
        "operationId": "envgroupEditPost",
        "summary": "Изменить информацию о группировке",
        "deprecated": false,
        "description": "Переименовывает группу профилей.\n- **Предварительные условия**: группа должна существовать в команде, у вызывающего должны быть права на неё, а новое имя не должно конфликтовать с другой группой. Проверка уникальности выполняется только если имя действительно меняется.\n- **Эффект**: переименовывает группу. Профили остаются в ней: они ссылаются на группу по идентификатору, поэтому больше ничего обновлять не нужно.\n- **Завершение**: синхронное и идемпотентное.",
        "tags": [
          "Group Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "groupName",
                  "id"
                ],
                "properties": {
                  "groupName": {
                    "type": "string",
                    "description": "Новое название группы окружений"
                  },
                  "id": {
                    "type": "string",
                    "description": "Уникальный идентификатор обновляемой группы"
                  }
                }
              },
              "example": {
                "groupName": "Group-1574544945848579",
                "id": "1574525425557584"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data` — одно значение типа boolean.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "boolean",
                      "description": "Результат"
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": null,
                  "data": true,
                  "requestId": "0d8b6f1c-9f4e-4d02-9d1a-7c3f5a1b2c3d"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envgroup/create": {
      "post": {
        "operationId": "envgroupCreatePost",
        "summary": "Добавить группу",
        "deprecated": false,
        "description": "Создаёт группу профилей.\n- **Предварительные условия**: имя не должно быть пустым, должно быть не длиннее 100 символов и не должно уже использоваться другой группой в команде. **Команда ограничена 1000 группами.**\n- **Эффект**: создаёт группу. Если команда выдаёт доступ по группам, а вызывающий не является владельцем, ему также выдаётся доступ к новой группе.\n- **Завершение**: синхронное; `data` содержит идентификатор новой группы.\n- **Повтор**: дублирующее имя отклоняется, а не приводит к повторному использованию существующей группы, поэтому повтор после успешного вызова, ответ на который вы не увидели, завершится ошибкой о дублировании имени — это признак того, что первый вызов сработал. Подтвердите через `/envgroup/page`.",
        "tags": [
          "Group Management"
        ],
        "parameters": [],
        "security": [
          {
            "Authorization": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data` — объект с полями `id` и `groupName`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "description": "Данные, возвращённые операцией",
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID группы",
                          "type": "string"
                        },
                        "groupName": {
                          "description": "Название группы",
                          "type": "string"
                        }
                      }
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": null,
                  "data": {
                    "id": "1673823102599682",
                    "groupName": "example-name"
                  },
                  "requestId": "0d8b6f1c-9f4e-4d02-9d1a-7c3f5a1b2c3d"
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envgroup/delete": {
      "post": {
        "operationId": "envgroupDeletePost",
        "summary": "Удалить группу",
        "deprecated": false,
        "description": "Удаляет одну или несколько групп профилей.\n- **Предварительные условия**: хотя бы один идентификатор должен разрешаться внутри команды, и у вызывающего должны быть права на него; неразрешённые идентификаторы молча игнорируются.\n- **Эффект**: удаляет группы и выданные по ним права участников. Профили браузера и облачные телефоны, которые в них находились, становятся без группы, поэтому висячих ссылок на группу не остаётся. Установка флага удаления окружений дополнительно перемещает профили, на которые у вас есть права, **в корзину**: они не уничтожаются, а на облачные телефоны этот флаг не влияет никогда.\n- **Завершение**: синхронное, но **не атомарное**. Группа удаляется первой, а последующие шаги всё ещё могут завершиться неудачно — например, если профиль запущен или передаётся, — и тогда группа окажется удалённой, а профили останутся на месте.\n- **Повтор**: перед повтором сверьтесь с `/envgroup/page` и списком профилей.\n\nЗадокументированные бизнес-ошибки: `19064`. Значения кодов см. в [Error Codes](../Getting%20Started/error-codes.md). Любая операция может дополнительно вернуть общие коды.",
        "tags": [
          "Group Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Уникальный идентификатор обновляемой группы"
                  },
                  "isDeleteAllEnv": {
                    "type": "boolean",
                    "description": "Удалить окружения в группе? false — не удалять, true — удалить"
                  }
                }
              },
              "example": {
                "ids": [
                  "string"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data` — одно значение типа boolean.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "boolean"
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": true,
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envtag/all": {
      "get": {
        "operationId": "envtagAllGet",
        "summary": "Получение списка тегов",
        "deprecated": false,
        "description": "Возвращает все метки профилей в команде.\n- **Эффект**: отсутствует. Только чтение. Повтор безопасен при ограниченной выдержке.\n- **Примечание**: этот эндпоинт **не поддерживает пагинацию, а у меток нет серверного ограничения**, поэтому ответ растёт вместе с числом меток, созданных вашей командой. Учитывайте это при проектировании клиента.",
        "tags": [
          "Tag Management"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Успех. `data` — массив объектов с полями `id` и `tagName`; пустой массив, если возвращать нечего.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "description": "ID тегов",
                            "type": "string"
                          },
                          "tagName": {
                            "description": "Название тегов",
                            "type": "string"
                          }
                        }
                      }
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": [
                    {
                      "id": "0",
                      "tagName": ""
                    }
                  ],
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envtag/create": {
      "post": {
        "operationId": "envtagCreatePost",
        "summary": "Создать теги",
        "deprecated": false,
        "description": "Создаёт метку профиля.\n- **Предварительные условия**: имя не должно быть пустым, должно быть не длиннее 100 символов и не должно уже использоваться другой меткой в команде.\n- **Эффект**: создаёт метку и возвращает её идентификатор. В отличие от групп, у меток нет ограничения по количеству.\n- **Повтор**: дублирующее имя отклоняется, а не приводит к повторному использованию существующей метки. Подтвердите через `/envtag/all`.",
        "tags": [
          "Tag Management"
        ],
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tagName": {
                    "type": "string",
                    "description": "название тега"
                  }
                }
              },
              "example": {
                "tagName": "Tag-123"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data` — объект с полями `id` и `tagName`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "ID тегов",
                          "type": "string"
                        },
                        "tagName": {
                          "description": "Название тегов",
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "tagName"
                      ]
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    },
                    "error": {
                      "type": "object",
                      "properties": {}
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": {
                    "id": "0",
                    "tagName": ""
                  },
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envtag/edit": {
      "post": {
        "operationId": "envtagEditPost",
        "summary": "Изменить информацию тегов",
        "deprecated": false,
        "description": "Переименовывает метку профиля.\n- **Предварительные условия**: метка должна существовать в команде, а новое имя не должно конфликтовать с другой меткой.\n- **Эффект**: переименовывает метку. Существующие привязки не затрагиваются, и профили сразу показывают новое имя.\n- **Завершение**: синхронное и идемпотентное.",
        "tags": [
          "Tag Management"
        ],
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "ID тега"
                  },
                  "tagName": {
                    "type": "string",
                    "description": "название тега"
                  }
                }
              },
              "example": {
                "id": "1564715845550177",
                "tagName": "Updated-123"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data` — одно значение типа boolean.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "boolean"
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    },
                    "error": {
                      "type": "object",
                      "properties": {}
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": true,
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/envtag/delete": {
      "post": {
        "operationId": "envtagDeletePost",
        "summary": "Удалить теги",
        "deprecated": false,
        "description": "Удаляет одну или несколько меток профилей.\n- **Предварительные условия**: хотя бы один идентификатор должен разрешаться внутри команды; неразрешённые молча игнорируются.\n- **Эффект**: удаляет метки. Метка исчезает у всех профилей, на которых была, и ни один профиль не удаляется. Этот эндпоинт управляет только метками профилей: метки файлов Cloud Storage управляются отдельно.\n- **Завершение**: синхронное. Повторный вызов сообщит, что метки недопустимы, а это значит, что первый вызов сработал.\n\nЗадокументированные бизнес-ошибки: `19105`. Значения кодов см. в [Error Codes](../Getting%20Started/error-codes.md). Любая операция может дополнительно вернуть общие коды.",
        "tags": [
          "Tag Management"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Уникальный ID обновляемого тега"
                  }
                }
              },
              "example": {
                "ids": [
                  "string"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data` — одно значение типа boolean.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "boolean"
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": true,
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    },
    "/webhook/config": {
      "post": {
        "operationId": "webhookConfigPost",
        "summary": "Настроить вебхук команды",
        "deprecated": false,
        "description": "Создаёт или заменяет конфигурацию вебхука команды.\n\n- **Предварительные условия**: `callbackUrl` должен быть HTTPS-URL длиной от 1 до 1024 символов, с именем хоста, без данных пользователя, без фрагмента и с корректным портом. Все адреса, в которые он разрешается, должны маршрутизироваться в интернете; диапазоны localhost, частные, link-local, CGNAT, метаданных облака, зарезервированные протоколом, документационные и 6to4 отклоняются. Та же проверка повторяется в момент открытия соединения при доставке, поэтому имя, которое позже разрешится в частный диапазон, приведёт к неудаче этой доставки, а не к обращению в вашу сеть.\n- **Действие**: выполняет upsert единственной конфигурации команды из серверного контекста. `teamId` никогда не читается из запроса, поэтому вызывающая сторона не может настроить другую команду. Эндпоинты Local API и Open API читают и пишут одну и ту же запись, а ответ повторяет сохранённое.\n- **Отключение**: `enabled: false` сохраняет URL и прекращает создание новых событий. Уже поставленные в очередь события отменяются по одному, если к моменту их авторизации конфигурация всё ещё отключена, поэтому быстрое повторное включение позволяет им продолжиться.\n- **Повтор**: безопасно. Сохранение — это upsert по команде, поэтому повторение того же запроса сходится к тому же состоянию.\n\nКонтракт обратного вызова, имена событий и расписание повторов см. в [Webhooks](../Getting%20Started/webhooks.md).\n\nЗадокументированные бизнес-ошибки: `41001`. Значения кодов см. в [Error Codes](../Getting%20Started/error-codes.md). Любая операция может дополнительно вернуть общие коды.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "callbackUrl": {
                    "description": "HTTPS-URL, принимающий события. От 1 до 1024 символов.",
                    "type": "string",
                    "maxLength": 1024
                  },
                  "enabled": {
                    "description": "Включена ли доставка для команды.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "callbackUrl",
                  "enabled"
                ]
              },
              "example": {
                "callbackUrl": "https://example.com/morelogin/webhook",
                "enabled": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Успех. `data` — объект с полями `callbackUrl` и `enabled`, повторяющий сохранённую конфигурацию.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "description": "Код результата. `0` — успех; другие коды означают ошибку.",
                      "type": "integer"
                    },
                    "msg": {
                      "description": "Сообщение об ошибке",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "callbackUrl": {
                          "description": "Сохранённый HTTPS-URL обратного вызова.",
                          "type": "string"
                        },
                        "enabled": {
                          "description": "Включена ли доставка для команды.",
                          "type": "boolean"
                        }
                      }
                    },
                    "requestId": {
                      "description": "Идентификатор запроса операции",
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "msg",
                    "data",
                    "requestId"
                  ]
                },
                "example": {
                  "code": 0,
                  "msg": "",
                  "data": {
                    "callbackUrl": "https://example.com/morelogin/webhook",
                    "enabled": true
                  },
                  "requestId": ""
                }
              }
            },
            "headers": {}
          }
        }
      }
    }
  },
  "webhooks": {
    "cloud_phone.power_on": {
      "post": {
        "operationId": "webhookCloudPhonePowerOn",
        "summary": "Включение облачного телефона завершено",
        "description": "Отправляется, когда включение достигло итогового результата.\n\n`success` равно `true` только если обратный вызов сервиса прошёл успешно и локальная синхронизация зафиксирована. Ошибка списания средств или асинхронная проверка прокси, которая завершилась неудачей и довела до конца свою очистку, сообщают о неудачном включении и не создают отдельного события выключения. Отложенные задачи, например установка предустановленных приложений, результат не меняют.\n\nЕсли загрузку прервала операция выключения, для этой попытки событие включения не создаётся; успешное выключение позже всё равно создаст собственное `cloud_phone.power_off`.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhoneWebhookEvent"
              },
              "example": {
                "eventId": "c7f3a2b10d8e4f6a9c1b2d3e4f5a6b7c",
                "eventType": "cloud_phone.power_on",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001"
                },
                "result": {
                  "success": false,
                  "code": "33318",
                  "message": "Operation failed"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_phone.power_off": {
      "post": {
        "operationId": "webhookCloudPhonePowerOff",
        "summary": "Облачный телефон выключен",
        "description": "Отправляется при успешном выключении. Неудачное выключение это событие не создаёт, поэтому здесь `result.success` всегда `true`.\n\n`data.reason` фиксирует причину остановки.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhonePowerOffWebhookEvent"
              },
              "example": {
                "eventId": "5b1d0c9e7a2f4d38b6c5a4e3f2d1c0b9",
                "eventType": "cloud_phone.power_off",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001",
                  "reason": "MONEY_SAVING"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_phone.restart": {
      "post": {
        "operationId": "webhookCloudPhoneRestart",
        "summary": "Перезапуск облачного телефона завершён",
        "description": "Отправляется, когда перезапуск достиг итогового результата. `success` равно `true` только если обратный вызов сервиса прошёл успешно и локальная синхронизация зафиксирована.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhoneWebhookEvent"
              },
              "example": {
                "eventId": "9e4c1a7b3f2d40518a6b5c4d3e2f1a0b",
                "eventType": "cloud_phone.restart",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_phone.reset": {
      "post": {
        "operationId": "webhookCloudPhoneReset",
        "summary": "Сброс облачного телефона завершён",
        "description": "Отправляется, когда сброс достиг итогового результата. `success` равно `true` только если обратный вызов сервиса прошёл успешно и локальная синхронизация зафиксирована.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhoneWebhookEvent"
              },
              "example": {
                "eventId": "2f8a6d4c0b9e47138c7d6e5f4a3b2c1d",
                "eventType": "cloud_phone.reset",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_phone.new_machine": {
      "post": {
        "operationId": "webhookCloudPhoneNewMachine",
        "summary": "Создание нового устройства одним щелчком для облачного телефона завершено",
        "description": "Отправляется, когда операция создания нового устройства одним щелчком достигла итогового результата. `success` равно `true` только если обратный вызов сервиса прошёл успешно и локальная синхронизация зафиксирована.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudPhoneWebhookEvent"
              },
              "example": {
                "eventId": "7c3b1e9d5a4f42068b1c2d3e4f5a6b70",
                "eventType": "cloud_phone.new_machine",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudPhoneId": "20001"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_browser.start": {
      "post": {
        "operationId": "webhookCloudBrowserStart",
        "summary": "Запуск облачного браузера завершён",
        "description": "Отправляется, когда запуск облачного браузера достиг итогового результата.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudBrowserWebhookEvent"
              },
              "example": {
                "eventId": "4a9f2c7e1b8d43509c6a5b4c3d2e1f00",
                "eventType": "cloud_browser.start",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudBrowserId": "30001",
                  "runId": "40001"
                },
                "result": {
                  "success": true,
                  "code": "0",
                  "message": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    },
    "cloud_browser.stop": {
      "post": {
        "operationId": "webhookCloudBrowserStop",
        "summary": "Остановка облачного браузера завершена",
        "description": "Отправляется при каждой попытке остановки облачного браузера, удачной или нет. Переход в состояние неудачной остановки сам по себе является неудачным результатом этой попытки; последующий повтор вручную или принудительное освобождение считаются новой операцией и получают новый `eventId`.\n\nСобытия дедуплицируются по операции остановки, поэтому одна попытка никогда не даёт два события, а две попытки никогда не объединяются. Внутренняя ошибка архивирования меняет только `result` и никогда не перезаписывает `reason`, зафиксированный в начале остановки.",
        "tags": [
          "Webhook Management"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookEventId"
          },
          {
            "$ref": "#/components/parameters/WebhookEventType"
          },
          {
            "$ref": "#/components/parameters/WebhookUserAgent"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloudBrowserStopWebhookEvent"
              },
              "example": {
                "eventId": "c7f3a2b10d8e4f6a9c1b2d3e4f5a6b7c",
                "eventType": "cloud_browser.stop",
                "eventTime": "1787241600000",
                "data": {
                  "teamId": "10001",
                  "cloudBrowserId": "30001",
                  "runId": "40001",
                  "reason": "BROWSER_EXITED"
                },
                "result": {
                  "success": false,
                  "code": "40006",
                  "message": "Operation failed"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "Authorization": {
        "type": "http",
        "description": "Значение поля access_token из ответа интерфейса получения токена доступа",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    },
    "parameters": {
      "WebhookEventId": {
        "name": "X-Webhook-Event-Id",
        "in": "header",
        "required": true,
        "description": "То же значение, что `eventId` в теле. Используйте его, чтобы обработчик был идемпотентным.",
        "schema": {
          "type": "string"
        }
      },
      "WebhookEventType": {
        "name": "X-Webhook-Event-Type",
        "in": "header",
        "required": true,
        "description": "То же значение, что `eventType` в теле, чтобы маршрутизировать без разбора тела.",
        "schema": {
          "type": "string"
        }
      },
      "WebhookUserAgent": {
        "name": "User-Agent",
        "in": "header",
        "required": true,
        "description": "Всегда `MoreLogin-Webhook/1.0`.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "WebhookAck": {
        "description": "Любой 2xx считается доставкой. Тело ответа игнорируется, поэтому отвечайте как можно раньше, а работу выполняйте асинхронно. Всё остальное, включая тайм-аут соединения или чтения, считается неудачей и повторяется."
      }
    },
    "schemas": {
      "WebhookResult": {
        "type": "object",
        "description": "Итоговый результат операции, которую описывает событие.",
        "properties": {
          "success": {
            "description": "Завершилась ли операция успешно.",
            "type": "boolean"
          },
          "code": {
            "description": "`0` при успехе. При неудаче — стабильный бизнес-код ошибки, не зависящий от языка.",
            "type": "string"
          },
          "message": {
            "description": "`null` при успехе. При неудаче — пояснение на языке команды; если язык или его текст недоступен, используется `en-US`.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "success",
          "code",
          "message"
        ]
      },
      "CloudPhoneWebhookEvent": {
        "type": "object",
        "properties": {
          "eventId": {
            "description": "Уникальный ID события. Повторы доставки и внутренние воспроизведения того же события используют его повторно, поэтому считайте его ключом идемпотентности.",
            "type": "string"
          },
          "eventType": {
            "description": "Стабильное имя события.",
            "type": "string"
          },
          "eventTime": {
            "description": "Когда наступил итоговый бизнес-результат, в миллисекундах эпохи Unix. Передаётся строкой.",
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "teamId": {
                "description": "Команда, которой принадлежит ресурс.",
                "type": "string"
              },
              "cloudPhoneId": {
                "description": "Облачный телефон, к которому относится событие.",
                "type": "string"
              }
            },
            "required": [
              "teamId",
              "cloudPhoneId"
            ]
          },
          "result": {
            "$ref": "#/components/schemas/WebhookResult"
          }
        },
        "required": [
          "eventId",
          "eventType",
          "eventTime",
          "data",
          "result"
        ]
      },
      "CloudPhonePowerOffWebhookEvent": {
        "type": "object",
        "properties": {
          "eventId": {
            "description": "Уникальный ID события. Повторы доставки и внутренние воспроизведения того же события используют его повторно, поэтому считайте его ключом идемпотентности.",
            "type": "string"
          },
          "eventType": {
            "description": "Стабильное имя события.",
            "type": "string"
          },
          "eventTime": {
            "description": "Когда наступил итоговый бизнес-результат, в миллисекундах эпохи Unix. Передаётся строкой.",
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "teamId": {
                "description": "Команда, которой принадлежит ресурс.",
                "type": "string"
              },
              "cloudPhoneId": {
                "description": "Облачный телефон, к которому относится событие.",
                "type": "string"
              },
              "reason": {
                "description": "Причина остановки телефона.",
                "type": "string",
                "enum": [
                  "NORMAL",
                  "MONEY_SAVING",
                  "OTHER"
                ]
              }
            },
            "required": [
              "teamId",
              "cloudPhoneId",
              "reason"
            ]
          },
          "result": {
            "$ref": "#/components/schemas/WebhookResult"
          }
        },
        "required": [
          "eventId",
          "eventType",
          "eventTime",
          "data",
          "result"
        ]
      },
      "CloudBrowserWebhookEvent": {
        "type": "object",
        "properties": {
          "eventId": {
            "description": "Уникальный ID события. Повторы доставки и внутренние воспроизведения того же события используют его повторно, поэтому считайте его ключом идемпотентности.",
            "type": "string"
          },
          "eventType": {
            "description": "Стабильное имя события.",
            "type": "string"
          },
          "eventTime": {
            "description": "Когда наступил итоговый бизнес-результат, в миллисекундах эпохи Unix. Передаётся строкой.",
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "teamId": {
                "description": "Команда, которой принадлежит ресурс.",
                "type": "string"
              },
              "cloudBrowserId": {
                "description": "Профиль облачного браузера, к которому относится событие.",
                "type": "string"
              },
              "runId": {
                "description": "Экземпляр запуска, к которому относится событие.",
                "type": "string"
              }
            },
            "required": [
              "teamId",
              "cloudBrowserId",
              "runId"
            ]
          },
          "result": {
            "$ref": "#/components/schemas/WebhookResult"
          }
        },
        "required": [
          "eventId",
          "eventType",
          "eventTime",
          "data",
          "result"
        ]
      },
      "CloudBrowserStopWebhookEvent": {
        "type": "object",
        "properties": {
          "eventId": {
            "description": "Уникальный ID события. Повторы доставки и внутренние воспроизведения того же события используют его повторно, поэтому считайте его ключом идемпотентности.",
            "type": "string"
          },
          "eventType": {
            "description": "Стабильное имя события.",
            "type": "string"
          },
          "eventTime": {
            "description": "Когда наступил итоговый бизнес-результат, в миллисекундах эпохи Unix. Передаётся строкой.",
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "teamId": {
                "description": "Команда, которой принадлежит ресурс.",
                "type": "string"
              },
              "cloudBrowserId": {
                "description": "Профиль облачного браузера, к которому относится событие.",
                "type": "string"
              },
              "runId": {
                "description": "Экземпляр запуска, к которому относится событие.",
                "type": "string"
              },
              "reason": {
                "description": "Причина остановки запуска.",
                "type": "string",
                "enum": [
                  "NORMAL",
                  "MONEY_SAVING",
                  "ENERGY_SAVING",
                  "BROWSER_EXITED",
                  "OTHER"
                ]
              }
            },
            "required": [
              "teamId",
              "cloudBrowserId",
              "runId",
              "reason"
            ]
          },
          "result": {
            "$ref": "#/components/schemas/WebhookResult"
          }
        },
        "required": [
          "eventId",
          "eventType",
          "eventTime",
          "data",
          "result"
        ]
      }
    }
  },
  "servers": [
    {
      "url": "https://api.morelogin.com",
      "description": "Эндпоинт MoreLogin Open API"
    }
  ],
  "security": [
    {
      "Authorization": []
    }
  ]
}